using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media;
using System;

namespace AvaloniaDrawingPad.Models
{
    // 选中状态变更事件参数
    public class ShapeSelectionChangedEventArgs : EventArgs
    {
        public bool IsSelected { get; }
        public SelectableShape Shape { get; }

        public ShapeSelectionChangedEventArgs(SelectableShape shape, bool isSelected)
        {
            Shape = shape;
            IsSelected = isSelected;
        }
    }

    public class SelectableShape
    {
        private readonly Canvas _canvas;
        private readonly Control _element; // 改为Control以支持Image和Shape
        private readonly Border _selectionBorder;
        private readonly Canvas _resizeHandles;
        private bool _isSelected = false;
        private bool _isResizing = false;
        private bool _isMoving = false; // 是否正在移动
        private ResizeHandle? _activeHandle = null;
        private Point _lastPoint;
        private const int SELECTION_PADDING = 10; // 增加选择区域的大小

        // 是否允许选中（只有在选择模式下才为true）
        private bool _selectionEnabled = false;
        
        // 添加移动和调整大小的回调
        public Action<Control, double, double, double, double>? MoveCommandCallback { get; set; }
        public Action<Control, double, double, double, double, double, double, double, double>? ResizeCommandCallback { get; set; }
        
        // 记录移动和调整大小的初始状态
        private double _initialLeft;
        private double _initialTop;
        private double _initialWidth;
        private double _initialHeight;

        // 添加选中状态变化事件
        public event EventHandler<ShapeSelectionChangedEventArgs>? SelectionChanged;

        public Control Element => _element;

        // 添加是否允许选中的属性
        public bool SelectionEnabled
        {
            get => _selectionEnabled;
            set => _selectionEnabled = value;
        }

        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                // 只有当值变化时才触发事件
                if (_isSelected != value)
                {
                    _isSelected = value;
                    _selectionBorder.IsVisible = value;
                    _resizeHandles.IsVisible = value;
                    if (value)
                    {
                        // 设置鼠标样式
                        _element.Cursor = new Cursor(StandardCursorType.SizeAll);
                    }
                    UpdateSelectionBorder();

                    // 触发选中状态变化事件
                    OnSelectionChanged(new ShapeSelectionChangedEventArgs(this, value));
                }
            }
        }

        // 触发选中事件的方法
        protected virtual void OnSelectionChanged(ShapeSelectionChangedEventArgs e)
        {
            SelectionChanged?.Invoke(this, e);
            Console.WriteLine($"图形选中状态已更改: {e.IsSelected}, 类型: {Element.GetType().Name}");
        }

        public SelectableShape(Canvas canvas, Control element)
        {
            _canvas = canvas;
            _element = element;

            // 创建选择边框
            _selectionBorder = new Border
            {
                BorderBrush = Brushes.Blue,
                BorderThickness = new Thickness(1),
                IsHitTestVisible = false,
                IsVisible = false
            };

            // 创建调整大小的手柄容器
            _resizeHandles = new Canvas
            {
                IsVisible = false
            };

            // 添加到画布
            canvas.Children.Add(_selectionBorder);
            canvas.Children.Add(_resizeHandles);

            // 创建调整大小的手柄
            CreateResizeHandles();

            // 添加事件处理
            _element.PointerPressed += Element_PointerPressed;
            _element.PointerReleased += Element_PointerReleased;
            _element.PointerMoved += Element_PointerMoved;

            // 初始化位置
            UpdateSelectionBorder();
        }

        private void CreateResizeHandles()
        {
            // 创建8个调整大小的手柄（四角和四边）
            CreateResizeHandle(ResizeHandlePosition.TopLeft);
            CreateResizeHandle(ResizeHandlePosition.Top);
            CreateResizeHandle(ResizeHandlePosition.TopRight);
            CreateResizeHandle(ResizeHandlePosition.Right);
            CreateResizeHandle(ResizeHandlePosition.BottomRight);
            CreateResizeHandle(ResizeHandlePosition.Bottom);
            CreateResizeHandle(ResizeHandlePosition.BottomLeft);
            CreateResizeHandle(ResizeHandlePosition.Left);
        }

        private void CreateResizeHandle(ResizeHandlePosition position)
        {
            var handle = new ResizeHandle(position);
            _resizeHandles.Children.Add(handle.Visual);

            handle.Visual.PointerPressed += ResizeHandle_PointerPressed;
            handle.Visual.PointerReleased += ResizeHandle_PointerReleased;

            handle.Visual.PointerMoved += (s, e) =>
            {
                if (_isResizing && _activeHandle != null)
                {
                    Point currentPoint = e.GetPosition(_canvas);
                    double deltaX = currentPoint.X - _lastPoint.X;
                    double deltaY = currentPoint.Y - _lastPoint.Y;

                    ResizeElement(deltaX, deltaY, _activeHandle.Position);

                    _lastPoint = currentPoint;
                    e.Handled = true;
                }
            };
        }

        private void Element_PointerPressed(object? sender, PointerPressedEventArgs e)
        {
            // 只有在启用选择的情况下才处理选择事件
            if (!_selectionEnabled)
            {
                // 在非选择模式下，不处理事件，允许事件继续传播
                return;
            }

            IsSelected = true;
            _isMoving = true;
            _lastPoint = e.GetPosition(_canvas);
            
            // 记录初始位置和大小
            _initialLeft = Canvas.GetLeft(_element);
            _initialTop = Canvas.GetTop(_element);
            _initialWidth = _element.Width;
            _initialHeight = _element.Height;
            
            e.Handled = true;
        }

        private void Element_PointerReleased(object? sender, PointerReleasedEventArgs e)
        {
            // 只有在启用选择的情况下才处理选择事件
            if (!_selectionEnabled)
            {
                // 在非选择模式下，不处理事件，允许事件继续传播
                return;
            }
            
            // 如果正在移动，创建移动命令
            if (_isMoving && !_isResizing)
            {
                double currentLeft = Canvas.GetLeft(_element);
                double currentTop = Canvas.GetTop(_element);
                
                // 如果位置有变化，创建移动命令
                if (Math.Abs(currentLeft - _initialLeft) > 0.1 || Math.Abs(currentTop - _initialTop) > 0.1)
                {
                    MoveCommandCallback?.Invoke(_element, _initialLeft, _initialTop, currentLeft, currentTop);
                }
            }
            
            _isMoving = false;
            e.Handled = true;
        }

        private void Element_PointerMoved(object? sender, PointerEventArgs e)
        {
            if (_isMoving && IsSelected && !_isResizing)
            {
                Point currentPoint = e.GetPosition(_canvas);
                double deltaX = currentPoint.X - _lastPoint.X;
                double deltaY = currentPoint.Y - _lastPoint.Y;

                MoveElement(deltaX, deltaY);

                _lastPoint = currentPoint;
                e.Handled = true;
            }
        }

        // 移动元素
        public void MoveElement(double deltaX, double deltaY)
        {
            if (_element is Line line)
            {
                // 移动线条
                line.StartPoint = new Point(line.StartPoint.X + deltaX, line.StartPoint.Y + deltaY);
                line.EndPoint = new Point(line.EndPoint.X + deltaX, line.EndPoint.Y + deltaY);
            }
            else
            {
                // 移动其他元素
                double left = Canvas.GetLeft(_element);
                double top = Canvas.GetTop(_element);

                Canvas.SetLeft(_element, left + deltaX);
                Canvas.SetTop(_element, top + deltaY);
            }

            // 更新选择边框
            UpdateSelectionBorder();
        }

        // 检查点是否在元素的扩展区域内（用于更容易选择线条）
        public bool HitTest(Point point)
        {
            try
            {
                if (_element is Canvas canvas)
                {
                    // 对于Canvas容器（自由曲线），检查点是否在容器内或接近边缘
                    double left = Canvas.GetLeft(canvas);
                    double top = Canvas.GetTop(canvas);
                    double right = left + canvas.Width;
                    double bottom = top + canvas.Height;

                    Console.WriteLine($"Canvas位置: 左={left}, 上={top}, 右={right}, 下={bottom}");
                    Console.WriteLine($"点位置: X={point.X}, Y={point.Y}");

                    // 首先检查点是否直接在Canvas的边界框内（放宽判断条件）
                    bool isDirectHit = point.X >= left - SELECTION_PADDING * 2 &&
                                     point.X <= right + SELECTION_PADDING * 2 &&
                                     point.Y >= top - SELECTION_PADDING * 2 &&
                                     point.Y <= bottom + SELECTION_PADDING * 2;

                    Console.WriteLine($"Canvas直接命中检测: {isDirectHit}");

                    if (isDirectHit)
                    {
                        Console.WriteLine($"Canvas子元素数量: {canvas.Children.Count}");

                        // 如果Canvas内没有子元素，直接返回true
                        if (canvas.Children.Count == 0)
                        {
                            Console.WriteLine("Canvas内无子元素，但仍然命中");
                            return true;
                        }

                        // 检查点是否接近Canvas中的任何线段
                        foreach (var child in canvas.Children)
                        {
                            Console.WriteLine($"检查Canvas子元素: {child.GetType().Name}");

                            if (child is Line line)
                            {
                                // 转换线段坐标到Canvas父级坐标系
                                Point startPoint = new Point(left + line.StartPoint.X, top + line.StartPoint.Y);
                                Point endPoint = new Point(left + line.EndPoint.X, top + line.EndPoint.Y);

                                Console.WriteLine($"线段: 从({startPoint.X}, {startPoint.Y})到({endPoint.X}, {endPoint.Y})");

                                bool nearLine = IsPointNearLine(point, startPoint, endPoint, SELECTION_PADDING * 2);
                                Console.WriteLine($"点是否接近线段: {nearLine}");

                                if (nearLine)
                                {
                                    return true;
                                }
                            }
                        }

                        // 即使没有接近任何线段，也返回命中，这更容易选中整个自由曲线
                        Console.WriteLine("未接近任何线段，但仍视为命中");
                        return true;
                    }

                    return false;
                }
                else if (_element is Shape shape)
                {
                    // 对于线条，创建一个更大的点击区域
                    if (shape is Line line)
                    {
                        return IsPointNearLine(point, line.StartPoint, line.EndPoint, SELECTION_PADDING);
                    }

                    // 对于其他形状，检查点是否在形状内或接近边缘
                    var result = shape.InputHitTest(point);
                    if (result != null)
                        return true;

                    // 检查点是否在形状的扩展区域内
                    double left = Canvas.GetLeft(shape);
                    double top = Canvas.GetTop(shape);
                    double right = left + shape.Width;
                    double bottom = top + shape.Height;

                    return point.X >= left - SELECTION_PADDING &&
                           point.X <= right + SELECTION_PADDING &&
                           point.Y >= top - SELECTION_PADDING &&
                           point.Y <= bottom + SELECTION_PADDING;
                }
                else if (_element is Image image)
                {
                    // 对于图片，检查点是否在图片内或接近边缘
                    double left = Canvas.GetLeft(image);
                    double top = Canvas.GetTop(image);
                    double right = left + image.Width;
                    double bottom = top + image.Height;

                    return point.X >= left - SELECTION_PADDING &&
                           point.X <= right + SELECTION_PADDING &&
                           point.Y >= top - SELECTION_PADDING &&
                           point.Y <= bottom + SELECTION_PADDING;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"HitTest出错: {ex.Message}");
            }

            return false;
        }

        // 检查点是否接近线段
        private bool IsPointNearLine(Point point, Point lineStart, Point lineEnd, double threshold)
        {
            double lineLength = Math.Sqrt(Math.Pow(lineEnd.X - lineStart.X, 2) + Math.Pow(lineEnd.Y - lineStart.Y, 2));
            if (lineLength == 0) return false;

            // 计算点到线的距离
            double distance = Math.Abs((lineEnd.Y - lineStart.Y) * point.X - (lineEnd.X - lineStart.X) * point.Y +
                                      lineEnd.X * lineStart.Y - lineEnd.Y * lineStart.X) / lineLength;

            // 检查点是否在线段的范围内
            double dotProduct = ((point.X - lineStart.X) * (lineEnd.X - lineStart.X) +
                                (point.Y - lineStart.Y) * (lineEnd.Y - lineStart.Y)) / (lineLength * lineLength);

            return distance <= threshold && dotProduct >= 0 && dotProduct <= 1;
        }

        public void UpdateSelectionBorder()
        {
            if (_element is Canvas canvas)
            {
                // Canvas容器（自由曲线）
                double left = Canvas.GetLeft(canvas);
                double top = Canvas.GetTop(canvas);
                double width = canvas.Width;
                double height = canvas.Height;

                Canvas.SetLeft(_selectionBorder, left - SELECTION_PADDING / 2);
                Canvas.SetTop(_selectionBorder, top - SELECTION_PADDING / 2);
                _selectionBorder.Width = width + SELECTION_PADDING;
                _selectionBorder.Height = height + SELECTION_PADDING;
            }
            else if (_element is Line line)
            {
                // 线条特殊处理
                double left = Math.Min(line.StartPoint.X, line.EndPoint.X);
                double top = Math.Min(line.StartPoint.Y, line.EndPoint.Y);
                double width = Math.Abs(line.EndPoint.X - line.StartPoint.X);
                double height = Math.Abs(line.EndPoint.Y - line.StartPoint.Y);

                Canvas.SetLeft(_selectionBorder, left - SELECTION_PADDING);
                Canvas.SetTop(_selectionBorder, top - SELECTION_PADDING);
                _selectionBorder.Width = width + SELECTION_PADDING * 2;
                _selectionBorder.Height = height + SELECTION_PADDING * 2;
            }
            else
            {
                // 其他元素
                double left = Canvas.GetLeft(_element);
                double top = Canvas.GetTop(_element);
                double width = _element.Width;
                double height = _element.Height;

                Canvas.SetLeft(_selectionBorder, left - SELECTION_PADDING / 2);
                Canvas.SetTop(_selectionBorder, top - SELECTION_PADDING / 2);
                _selectionBorder.Width = width + SELECTION_PADDING;
                _selectionBorder.Height = height + SELECTION_PADDING;
            }

            UpdateResizeHandles();
        }

        private void UpdateResizeHandles()
        {
            double left = Canvas.GetLeft(_selectionBorder);
            double top = Canvas.GetTop(_selectionBorder);
            double width = _selectionBorder.Width;
            double height = _selectionBorder.Height;

            foreach (var child in _resizeHandles.Children)
            {
                if (child is Rectangle handle)
                {
                    var position = (ResizeHandlePosition)handle.Tag!;

                    switch (position)
                    {
                        case ResizeHandlePosition.TopLeft:
                            Canvas.SetLeft(handle, left - 4);
                            Canvas.SetTop(handle, top - 4);
                            break;
                        case ResizeHandlePosition.Top:
                            Canvas.SetLeft(handle, left + width / 2 - 4);
                            Canvas.SetTop(handle, top - 4);
                            break;
                        case ResizeHandlePosition.TopRight:
                            Canvas.SetLeft(handle, left + width - 4);
                            Canvas.SetTop(handle, top - 4);
                            break;
                        case ResizeHandlePosition.Right:
                            Canvas.SetLeft(handle, left + width - 4);
                            Canvas.SetTop(handle, top + height / 2 - 4);
                            break;
                        case ResizeHandlePosition.BottomRight:
                            Canvas.SetLeft(handle, left + width - 4);
                            Canvas.SetTop(handle, top + height - 4);
                            break;
                        case ResizeHandlePosition.Bottom:
                            Canvas.SetLeft(handle, left + width / 2 - 4);
                            Canvas.SetTop(handle, top + height - 4);
                            break;
                        case ResizeHandlePosition.BottomLeft:
                            Canvas.SetLeft(handle, left - 4);
                            Canvas.SetTop(handle, top + height - 4);
                            break;
                        case ResizeHandlePosition.Left:
                            Canvas.SetLeft(handle, left - 4);
                            Canvas.SetTop(handle, top + height / 2 - 4);
                            break;
                    }
                }
            }
        }

        private void ResizeElement(double deltaX, double deltaY, ResizeHandlePosition position)
        {
            if (_element is Line line)
            {
                // 调整线条大小
                switch (position)
                {
                    case ResizeHandlePosition.TopLeft:
                        line.StartPoint = new Point(line.StartPoint.X + deltaX, line.StartPoint.Y + deltaY);
                        break;
                    case ResizeHandlePosition.BottomRight:
                        line.EndPoint = new Point(line.EndPoint.X + deltaX, line.EndPoint.Y + deltaY);
                        break;
                }
            }
            else
            {
                // 调整其他元素大小
                double left = Canvas.GetLeft(_element);
                double top = Canvas.GetTop(_element);
                double width = _element.Width;
                double height = _element.Height;

                switch (position)
                {
                    case ResizeHandlePosition.TopLeft:
                        Canvas.SetLeft(_element, left + deltaX);
                        Canvas.SetTop(_element, top + deltaY);
                        _element.Width = width - deltaX;
                        _element.Height = height - deltaY;
                        break;
                    case ResizeHandlePosition.Top:
                        Canvas.SetTop(_element, top + deltaY);
                        _element.Height = height - deltaY;
                        break;
                    case ResizeHandlePosition.TopRight:
                        Canvas.SetTop(_element, top + deltaY);
                        _element.Width = width + deltaX;
                        _element.Height = height - deltaY;
                        break;
                    case ResizeHandlePosition.Right:
                        _element.Width = width + deltaX;
                        break;
                    case ResizeHandlePosition.BottomRight:
                        _element.Width = width + deltaX;
                        _element.Height = height + deltaY;
                        break;
                    case ResizeHandlePosition.Bottom:
                        _element.Height = height + deltaY;
                        break;
                    case ResizeHandlePosition.BottomLeft:
                        Canvas.SetLeft(_element, left + deltaX);
                        _element.Width = width - deltaX;
                        _element.Height = height + deltaY;
                        break;
                    case ResizeHandlePosition.Left:
                        Canvas.SetLeft(_element, left + deltaX);
                        _element.Width = width - deltaX;
                        break;
                }
            }

            UpdateSelectionBorder();
        }

        private void ResizeHandle_PointerPressed(object? sender, PointerPressedEventArgs e)
        {
            if (sender is ResizeHandle handle)
            {
                _activeHandle = handle;
                _isResizing = true;
                _lastPoint = e.GetPosition(_canvas);
                
                // 记录初始位置和大小
                _initialLeft = Canvas.GetLeft(_element);
                _initialTop = Canvas.GetTop(_element);
                _initialWidth = _element.Width;
                _initialHeight = _element.Height;
                
                e.Handled = true;
            }
        }

        private void ResizeHandle_PointerReleased(object? sender, PointerReleasedEventArgs e)
        {
            if (_isResizing && _activeHandle != null)
            {
                // 获取当前位置和大小
                double currentLeft = Canvas.GetLeft(_element);
                double currentTop = Canvas.GetTop(_element);
                double currentWidth = _element.Width;
                double currentHeight = _element.Height;
                
                // 如果大小或位置有变化，创建调整大小命令
                if (Math.Abs(currentLeft - _initialLeft) > 0.1 || 
                    Math.Abs(currentTop - _initialTop) > 0.1 ||
                    Math.Abs(currentWidth - _initialWidth) > 0.1 ||
                    Math.Abs(currentHeight - _initialHeight) > 0.1)
                {
                    ResizeCommandCallback?.Invoke(
                        _element, 
                        _initialLeft, _initialTop, _initialWidth, _initialHeight,
                        currentLeft, currentTop, currentWidth, currentHeight);
                }
                
                _isResizing = false;
                _activeHandle = null;
                e.Handled = true;
            }
        }
    }

    public enum ResizeHandlePosition
    {
        TopLeft,
        Top,
        TopRight,
        Right,
        BottomRight,
        Bottom,
        BottomLeft,
        Left
    }

    public class ResizeHandle
    {
        public Rectangle Visual { get; }
        public ResizeHandlePosition Position { get; }

        public ResizeHandle(ResizeHandlePosition position)
        {
            Position = position;
            Visual = new Rectangle
            {
                Width = 8,
                Height = 8,
                Fill = Brushes.White,
                Stroke = Brushes.Blue,
                StrokeThickness = 1,
                Tag = position
            };

            // 设置鼠标样式
            switch (position)
            {
                case ResizeHandlePosition.TopLeft:
                case ResizeHandlePosition.BottomRight:
                    Visual.Cursor = new Cursor(StandardCursorType.TopLeftCorner);
                    break;
                case ResizeHandlePosition.TopRight:
                case ResizeHandlePosition.BottomLeft:
                    Visual.Cursor = new Cursor(StandardCursorType.TopRightCorner);
                    break;
                case ResizeHandlePosition.Top:
                case ResizeHandlePosition.Bottom:
                    Visual.Cursor = new Cursor(StandardCursorType.SizeNorthSouth);
                    break;
                case ResizeHandlePosition.Left:
                case ResizeHandlePosition.Right:
                    Visual.Cursor = new Cursor(StandardCursorType.SizeWestEast);
                    break;
            }
        }
    }
}